package com.atguigu.consumer;

import com.atguigu.constant.MqConst;
import com.atguigu.constant.RedisConst;
import com.atguigu.entity.SeckillProduct;
import com.atguigu.entity.UserSeckillSkuInfo;
import com.atguigu.service.SeckillProductService;
import com.atguigu.utils.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

@Component
public class SecKillConsumer {
    @Autowired
    private SeckillProductService seckillProductService;
    @Autowired
    private RedisTemplate redisTemplate;
    //1.扫描当天符合条件的商品到redis当中
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value= MqConst.SCAN_SECKILL_QUEUE,durable = "false"),
            exchange = @Exchange(value =MqConst.SCAN_SECKILL_EXCHANGE,durable = "false"),
            key = {MqConst.SCAN_SECKILL_ROUTE_KEY}
    ))
    public void scanSeckillProductToRedis(Message message, Channel channel) throws Exception{
        QueryWrapper<SeckillProduct> wrapper = new QueryWrapper<>();
        //a.扫描已经通过审核的秒杀商品
        wrapper.eq("status",1);
        //b.剩余库存要大于0
        wrapper.gt("num",0);
        //c.取出当天日期  select * from seckill_product where start_time>'2022-01-21'
        //2022-01-21 08:21:03
        //2022-01-21 03:21:03
        wrapper.ge("DATE_FORMAT(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
        List<SeckillProduct> seckillProductList = seckillProductService.list(wrapper);
        //d.把秒杀商品放入到redis当中
        if(!CollectionUtils.isEmpty(seckillProductList)){
            for (SeckillProduct seckillProduct : seckillProductList) {
                //以hash结构存储秒杀商品信息
                redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).put(seckillProduct.getSkuId().toString(),seckillProduct);
                //把商品数量放入redis队列当中
                for (int i = 0; i <seckillProduct.getNum() ; i++) {
                    redisTemplate.boundListOps(RedisConst.SECKILL_STOCK_PREFIX+seckillProduct.getSkuId())
                            .leftPush(seckillProduct.getSkuId().toString());
                }
                //通知并修改秒杀状态位
                redisTemplate.convertAndSend(RedisConst.PREPARE_PUB_SUB_SECKILL,seckillProduct.getSkuId()+":"+RedisConst.CAN_SECKILL);

            }
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //2.秒杀商品预下单消费端编写
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value= MqConst.PREPARE_SECKILL_QUEUE,durable = "false"),
            exchange = @Exchange(value =MqConst.PREPARE_SECKILL_EXCHANGE,durable = "false"),
            key = {MqConst.PREPARE_SECKILL_ROUTE_KEY}
    ))
    public void prepareSecKill(UserSeckillSkuInfo userSeckillSkuInfo,Message message, Channel channel) throws Exception{
        if(userSeckillSkuInfo!=null){
            //开始预下单处理逻辑
            seckillProductService.prepareSecKill(userSeckillSkuInfo);
        }
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //3.秒杀商品结束之后的善后工作
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value= MqConst.CLEAR_REDIS_QUEUE,durable = "false"),
            exchange = @Exchange(value =MqConst.CLEAR_REDIS_EXCHANGE,durable = "false"),
            key = {MqConst.CLEAR_REDIS_ROUTE_KEY}
    ))
    public void clearSeckill(Message message, Channel channel) throws Exception{
        //1.把小于等于当前时间的商品下架(3点执行)
        QueryWrapper<SeckillProduct> wrapper = new QueryWrapper<>();
        //a.扫描已经通过审核的秒杀商品
        wrapper.eq("status",1);
        //结束时间要小于等于当前时间
        wrapper.le("end_time",new Date());
        List<SeckillProduct> seckillProductList = seckillProductService.list(wrapper);
        if(!CollectionUtils.isEmpty(seckillProductList)){
            for (SeckillProduct seckillProduct : seckillProductList) {
                //2.删除该商品对于的库存与状态位
                redisTemplate.delete(RedisConst.SECKILL_STATE_PREFIX+seckillProduct.getSkuId());
                redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX+seckillProduct.getSkuId());
                //对该商品状态改为2
                seckillProduct.setStatus("2");
                seckillProductService.updateById(seckillProduct);
            }
        }
        //3.redis里面其他信息删掉
        redisTemplate.delete(RedisConst.SECKILL_PRODUCT);
        redisTemplate.delete(RedisConst.PREPARE_SECKILL_USERID_ORDER);
        redisTemplate.delete(RedisConst.PREPARE_SECKILL_USERID_SKUID);
        //已经抢购到的订单信息
        redisTemplate.delete(RedisConst.BOUGHT_SECKILL_USER_ORDER);
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

}
